<?php

    /**
     * Meter
     *
     * @package      Core
     * @subpackage   Meter
     * 
     * @license      GNU Lesser General Public Licence see LICENCE-LGPL file or http://www.gnu.org/licenses/lgpl.html
     */
    class Core_Meter
    {

    ////////////////////////////////////////////////////////////////////////////
    //                                Variables                               //
    ////////////////////////////////////////////////////////////////////////////

        /**
         * Singleton instance
         *
         * @var Core_Meter
         */
        private static $_instance = null;

        /**
         * List of intervals
         *
         * @var array
         */
        private $_intervals = array();

        /**
         * Doctrine SQL profiler
         *
         * @var Doctrine_Connection_Profiler
         */
        private $_profiler = null;

    ////////////////////////////////////////////////////////////////////////////
    //                             Static Methods                             //
    ////////////////////////////////////////////////////////////////////////////

        /**
         * Singleton instance
         *
         * @return      Core_Meter
         */
        public static function getInstance()
        {
            if (self::$_instance === null) {
                self::$_instance = new self();
            }

            return self::$_instance;
        }

    ////////////////////////////////////////////////////////////////////////////
    //                            Getters / Setters                           //
    ////////////////////////////////////////////////////////////////////////////

        /**
         * Gets the time of the requested interval
         *
         * @param       integer     $number
         * @return      array
         */
        public function getInterval($interval = null)
        {
            if ($interval === null) {
                // Return the last interval
                $interval = ($this->countIntervals() - 1);
            } else {
                $interval = intval($interval);
            }

            return (isset($this->_intervals[$interval])) ? $this->_intervals[$interval] : array();
        }

        /**
         * Sets the Doctrine's profiler object
         *
         * @param       Doctrine_Connection_Profiler     $profiler
         * @throws      Core_ArgumentNullException
         * @return      Core_Meter
         */
        public function setSqlProfiler(Doctrine_Connection_Profiler $profiler)
        {
            if ($profiler === null) {
                throw new Core_ArgumentNullException('profiler is a null reference');
            }

            $this->_profiler = $profiler;
            return $this;
        }

        /**
         * Gets a formatted javascript version for Firebug
         *
         * @return      string
         */
        public function getFirebugText()
        {
            $info     = '';
            $display  = '<script type="text/javascript">if(console){';

            foreach ($this->_intervals as $key => $interval) {
                if ($key > 0) {
                    $info .= 'console.info("'. $this->displayInterval($key, true) .'");';
                }
            }

            $display .= 'console.group("Total display time : '. number_format($this->displayTotalTime(), 6) .' s");';
            $display .= $info;
            $display .= 'console.groupEnd();';

            if ($this->_profiler !== null) {
                $time = 0;
                $info = '';

                foreach ($this->_profiler as $event) {
                    $time += $event->getElapsedSecs();

                    // Displays queries
//                    $info .= 'console.info("'. $event->getName() .' : '. $event->getElapsedSecs() ."\\n";
//                    $info .= $event->getQuery() .'");';
                }

                $display .= 'console.group("Total SQL time : '. number_format($time, 6) .' s");';
                $display .= $info;
                $display .= 'console.groupEnd();';
            }

            $display .= '}else{alert("Please enable Firebug to view display information.");}</script>';

            return $display;
        }

    ////////////////////////////////////////////////////////////////////////////
    //                                 Methods                                //
    ////////////////////////////////////////////////////////////////////////////

        /**
         * Constructor
         *
         * Marked as protected to prevent non static calls
         */
        protected function __construct() {}

        /**
         * Destructor
         */
        public function __destruct()
        {
            $this->_intervals = array();
            unset($this);
        }

        /**
         * Gets the number of intervals
         *
         * @return      integer
         */
        public function countIntervals()
        {
            return count($this->_intervals);
        }

        /**
         * Sets a new interval
         *
         * @param       string      $name
         * @return      void
         */
        public function markInterval($name = null)
        {
            $this->_intervals[] = array('name' => $name, 'time' => microtime(true));
        }

        /**
         * Marks the first interval
         *
         * @return      void
         */
        public function start()
        {
            $this->markInterval('Start');
        }

        /**
         * Displays interval information
         *
         * @param       integer     $interval
         * @param       boolean     $fromStart
         * @return      string
         */
        public function displayInterval($interval = null, $fromStart = false)
        {
            if ($interval === null) {
                // Return the last interval
                $interval = ($this->countIntervals() - 1);
            } else {
                if (intval($interval) == 0) {
                    $stop = $this->getInterval(0);
                    return $stop['name'] .' : 0';
                } else {
                    $interval = intval($interval);
                }
            }

            if ($fromStart) {
                $start = $this->getInterval(0);
            } else {
                $start = $this->getInterval($interval - 1);
            }

            $stop = $this->getInterval($interval);

            return $stop['name'] .' at '. number_format($stop['time'] - $start['time'], 6) .' s';
        }

        /**
         * Displays the total time
         *
         * @return      string
         */
        public function displayTotalTime()
        {
            $count = $this->countIntervals();

            if ($count > 1) {
                $start = $this->getInterval(0);
                $stop  = $this->getInterval($count - 1);

                return  $stop['time'] - $start['time'];
            } else {
                return 0;
            }
        }
    }
